package com.wei.web.middleware.retry.compensate.distribution;

import com.tuya.biz.platform.framework.config.EnvironmentContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.zookeeper.CreateMode;

import java.util.List;

/**
 * @author shihuimiao
 * create time: 下午5:26
 */
@Slf4j
public class NodeSlice {

    private final CuratorFramework curatorFramework;

    /**
     * 标识
     */
    private String identity;

    private static final String path = "/biz-parent-compensate-node/" + EnvironmentContext.getAppName();

    private static final String splitStr = "_slice_";

    private NodeSliceModel nodeSliceModel = new NodeSliceModel(0, 1);

    public NodeSlice(CuratorFramework curatorFramework) {
        this.curatorFramework = curatorFramework;
        this.identity = getIdentification();
        init();
        refreshSlice();
    }

    private void init() {
        try {
            PathChildrenCache cache =
                    new PathChildrenCache(curatorFramework, path, false);
            cache.getListenable().addListener((curatorFramework, event) -> {
                refreshSlice();
            });
            cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
        } catch (Exception e) {
            log.error("slice init error", e);
        }
    }

    private synchronized void refreshSlice(){
        int retry = 2;
        boolean identityEffective = false;
        while (!identityEffective && retry > 0) {
            try {
                List<String> nodes = this.curatorFramework.getChildren().forPath(path);
                log.info("nodes info {};identity {}", nodes, identity);
                if (CollectionUtils.isNotEmpty(nodes)) {
                    for (int i = 0; i < nodes.size(); i++) {
                        String node = nodes.get(i);
                        if (node.equals(identity)) {
                            nodeSliceModel.setNum(i);
                            nodeSliceModel.setTotal(nodes.size());
                            identityEffective = true;
                        }
                    }
                }
            } catch (Exception e) {
                log.warn("slice get zk nodes error", e);
            } finally {
                /** 防止zk会话断了 重新注册 */
                if (!identityEffective) {
                    log.info("slice identity wrong retry;identity={}", identity);
                    identity = getIdentification();
                }
                retry--;
            }
        }
    }

    private String getIdentification() {
        try {
            String nodePath = path + "/" + splitStr;

            String newIdentity = this.curatorFramework.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                    .forPath(nodePath);

            log.info("slice node path is={},newIdentity={}", nodePath, newIdentity);

            if (StringUtils.isNotBlank(newIdentity)) {
                String[] split = newIdentity.split(splitStr);
                if (split.length == 2) {
                    return splitStr + split[1];
                }
            }
        } catch (Exception e) {
            log.error("slice create path error", e);
        }
        return null;
    }

    public NodeSliceModel getSliceModel() {
        return nodeSliceModel;
    }

}
